package SpLib.Com
{	
	public class BigInt
	{		
		private var m_Sign:Boolean;			//正负
		private var m_Data:Array;			//数据区
		
		public function BigInt(...arg)
		{
			m_Sign = true;
			var init:Boolean = false;
			
			switch(arg.length)
			{
			case 0:
			{
				init = true;
				m_Data = new Array(1);
			}
			break;
			case 1:
			{
				copy(GetFrom(arg[0]));	
			}
			break;
			default:
			{
				init = true;
				m_Data = new Array(1);
			}
			}
			
			if(init)
			{
				var i:int;
				for(i=0;i<m_Data.length;i++)
				{
					m_Data[i] = 0;
				}
			}
		}
		
		public function copy(rhs:BigInt):void
		{
			m_Sign = rhs.m_Sign;
			
			m_Data = new Array(rhs.m_Data.length);
			var i:int;
			for(i=0;i<m_Data.length;i++)
			{
				m_Data[i] = rhs.m_Data[i];
			}
		}
		
		public function clone():BigInt
		{
			var d:BigInt = new BigInt;
			
			d.m_Sign = m_Sign;
			
			d.m_Data = new Array(m_Data.length);
			var i:int;
			for(i=0;i<m_Data.length;i++)
			{
				d.m_Data[i] = m_Data[i];
			}
			
			return d;
		}
		
		public function compare(rhs:BigInt):int
		{
			var i:int;
			
			//正/负
			if(m_Sign && !rhs.m_Sign) return 1;
			
			//负/正
			if(!m_Sign && rhs.m_Sign) return -1;
			
			//都是正数
			if(m_Sign && rhs.m_Sign)
			{
				if(m_Data.length>rhs.m_Data.length)
					return 1;
				
				if(m_Data.length<rhs.m_Data.length)
					return -1;
					
				//高位到低位比较
				for(i=(m_Data.length-1);i>=0;i--)
				{
					if(m_Data[i]>rhs.m_Data[i]) return 1;
					if(m_Data[i]<rhs.m_Data[i]) return -1;
				}
				
				return 0;
			}
			
			//都是负数
			if(m_Data.length>rhs.m_Data.length)
				return -1;
				
			if(m_Data.length<rhs.m_Data.length)
				return 1;
				
			//高位到低位比较	
			for(i=(m_Data.length-1);i>=0;i--)
			{
				if(m_Data[i]>rhs.m_Data[i]) return -1;
				if(m_Data[i]<rhs.m_Data[i]) return 1;
			}
				
			return 0;
		}
		
		//移除头部0
		public function removeblank():void
		{
			var i:int;
			var pos:int = -1;
			for(i=(m_Data.length-1);i>=0;i--)
			{
				if(m_Data[i]!=0)
				{
					//找到第一个不为0的高位
					pos = i;
					break;
				}
			}
			
			var num:int = m_Data.length-pos-1;
			for(i=0;i<num;i++)
			{
				m_Data.pop();
			}
		}
		
		public static function add(a1:BigInt,a2:BigInt):BigInt
		{
			var a:BigInt = new BigInt;
			var i:int;
			var minlen:int;
			var c:int = 0;
			
			//正数相加
			if(a1.m_Sign && a2.m_Sign)
			{
				minlen = Math.min(a1.m_Data.length,a2.m_Data.length);
				c = 0;
				for(i=0;i<minlen;i++)
				{
					c += a1.m_Data[i] + a2.m_Data[i];
					a.m_Data.push(c%10);
					c = c/10;
				}
				
				if(a1.m_Data.length==a2.m_Data.length)
				{
					a.m_Data.push(c%10);
				}
				else
				{
					if(a1.m_Data.length<a2.m_Data.length)
					{
						for(i=minlen;i<a2.m_Data.length;i++)
						{
							c += a2.m_Data[i];
							a.m_Data.push(c%10);
							c = c/10;
						}
					}
					else
					{
						for(i=minlen;i<a1.m_Data.length;i++)
						{
							c += a1.m_Data[i];
							a.m_Data.push(c%10);
							c = c/10;
						}
					}
					
					a.m_Data.push(c%10);
				}
				
				a.removeblank();
			}
			
			//负数相加
			if(!a1.m_Sign && !a2.m_Sign)
			{
				minlen =  Math.min(a1.m_Data.length,a2.m_Data.length);
				c = 0;
				for(i=0;i<minlen;i++)
				{
					c += a1.m_Data[i] + a2.m_Data[i];
					a.m_Data.push(c%10);
					c = c/10;
				}
				
				if(a1.m_Data.length==a2.m_Data.length)
				{
					a.m_Data.push(c%10);
				}
				else
				{
					if(a1.m_Data.length<a2.m_Data.length)
					{
						for(i=minlen;i<a2.m_Data.length;i++)
						{
							c += a2.m_Data[i];
							a.m_Data.push(c%10);
							c = c/10;
						}
					}
					else
					{
						for(i=minlen;i<a1.m_Data.length;i++)
						{
							c += a1.m_Data[i];
							a.m_Data.push(c%10);
							c = c/10;
						}
					}
					
					a.m_Data.push(c%10);
				}
				
				a.removeblank();
				a.m_Sign = false;
			}
			
			var a3:BigInt;
			//正  + 负
			if(a1.m_Sign && !a2.m_Sign)
			{
				a3 = a2.clone();
				a3.m_Sign = false;
				return dec(a1,a3);
			}
			
			//负  + 正
			if(!a1.m_Sign && a2.m_Sign)
			{
				a3 = a1.clone();
				a3.m_Sign = false;
				return dec(a1,a3);
			}
			
			return a;
		}
		
		public static function dec(a1:BigInt,a2:BigInt):BigInt
		{
			var a:BigInt = new BigInt;
			
			//正数相减
			if(a1.m_Sign && a2.m_Sign)
			{
				var com:int = a1.compare(a2);
				switch(com)
				{
				case 0:return a;
				case 1:
				{
					
				}
				break;
				case 2:
				{
					
				}
				break;
				}
				
			}
			
			var a3:BigInt;
			//正 - 负
			if(a1.m_Sign && !a2.m_Sign)
			{
				a3 = a2.clone();
				a3.m_Sign = true;
				return add(a1,a3);
			}
			
			//负  - 正
			if(!a1.m_Sign && a2.m_Sign)
			{
				a3 = a2.clone();
				a3.m_Sign = false;
				return add(a1,a2);
			}
			
			return a;
		}
		
		public static function GetFrom(d:*):BigInt
		{
			if(typeof(d) == "object")
			{
				if(d is BigInt) return (d as BigInt).clone();
				return new BigInt();
			}
			
			if(typeof(d) == "string")
			{
				return GetFromString(d as String);
			}
			
			if(typeof(d) == "number") 
			{
				return GetFromNumber(d as Number);
			}
			
			return new BigInt();
		}
		
		public static function GetFromString(d:String):BigInt
		{
			var n:BigInt = new BigInt;
			
			var f:String = d.charAt(0);
			
			//自定义的特定编码字串
			if(f=="I" && d.length>=3)
			{
				if(d.charAt(1)==":")
				{
					return GetFromString(d.substr(2));
				}
				
				return n;
			}
			
			//负值
			if(f=="-" && d.length>=2)
			{
				n.m_Sign = false;
				d = d.substr(1);
			}
			
			if(f=="+" && d.length>=2)
			{
				d = d.substr(1);
			}
			
			var i:int;
			n.m_Data =  new Array;
			for(i=(d.length-1);i>=0;i--)
			{
				var c:String = d.charAt(i);
				
				switch(c)
				{
				case "1":n.m_Data.push(1);break;
				case "2":n.m_Data.push(2);break;
				case "3":n.m_Data.push(3);break;
				case "4":n.m_Data.push(4);break;
				case "5":n.m_Data.push(5);break;
				case "6":n.m_Data.push(6);break;
				case "7":n.m_Data.push(7);break;
				case "8":n.m_Data.push(8);break;
				case "9":n.m_Data.push(9);break;
				case "0":n.m_Data.push(0);break;
				}
			}
			
			n.removeblank();
			
			return n;
		}
		
		public static function GetFromNumber(d:Number):BigInt
		{
			return GetFromString(d.toString())
		}
		
		public function toString():String
		{
			var str:String;
			if(m_Sign) str = "-";
		
			var i:int;
			for(i=(m_Data.length-1);i>=0;i--)
			{
				switch(m_Data[i])
				{
				case 0:str+="0";break;
				case 1:str+="1";break;
				case 2:str+="2";break;
				case 3:str+="3";break;
				case 4:str+="4";break;
				case 5:str+="5";break;
				case 6:str+="6";break;
				case 7:str+="7";break;
				case 8:str+="8";break;
				case 9:str+="9";break;
				}
			}
			
			return str;
		}
	}
}